﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.HomeServer.Controls;
using Umbrella.Net.Contracts;
using Umbrella.Whs.SharePoint;
using Umbrella.Whs.WhsAddin.Controls;

namespace Umbrella.Whs.WhsAddin.Wizards.SharePointInstallation
{
    internal partial class Step40_Install : WizardPageClientBannerTop
    {
        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(Step40_Install));
        private InstallationManager _instMgr = new InstallationManager();
        private InstallationPackagesManager _instPackMgr = new InstallationPackagesManager();
        private IList<IInstallStep> _installSteps;

        private SharePointInstallationWizard ParentWizard2
        {
            get { return (SharePointInstallationWizard)this.ParentWizard; }
        }

        public Step40_Install()
        {
            InitializeComponent();

            // initialize
            this.filledBar.Value1 = 0;
            this.statusLabel.Text = Resources.txtPreparing;
        }

        public override void StartRealWork()
        {
            base.StartRealWork();

            // create installation steps
            CreateInstallationSteps();

            // start installation
            this.installerBgWorker.RunWorkerAsync();
        }

        private void CreateInstallationSteps()
        {
            var steps = new List<IInstallStep>();

            // at first, install SSEE
            if (!_instMgr.IsSSEEInstalled)
                steps.Add(new InstallStepSqlServerEmbeddedEdition(_instPackMgr.GetCoreExtractionDirectory()));

            // install SharePoint core first,
            // then the language packs
            {
                var ips = (
                    from ip in this.ParentWizard2.SelectedInstallationFiles
                    orderby (ip.LanguageLCID == InstallationManager.RootLanguageLCID) descending
                    select ip
                    );

                foreach (var ip in ips)
                {
                    var ipTitle = this.ParentWizard2.GetTitleForInstallationPackage(ip);

                    steps.Add(new InstallStepSharePointSetup(ip, ipTitle));
                }
            }

            // create service account
            steps.Add(new InstallStepCreateServiceAccount());

            // configure configdb and central administration, etc.
            // all the psconfig stuff
            steps.Add(new InstallStepConfigDbAndCentralAdmin());
            steps.Add(new InstallStepProvisionCentralAdmin());
            steps.Add(new InstallStepInstallServices());
            steps.Add(new InstallStepSecureResources());
            steps.Add(new InstallStepConfigureSearch());
            steps.Add(new InstallStepInstallFeatures());

            // create website
            steps.Add(new InstallStepCreateUmbrellaWebsite(
                from l in this.ParentWizard2.SelectedInstallationFiles 
                select l.LanguageLCID
                ));

            // finally, clean up temp stuff
            steps.Add(new InstallStepCleanupTemp());

            // finalize
            steps.Add(new InstallStepFinalize());

            _installSteps = steps.AsReadOnly();
        }

        private void installerBgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // determine total weight
            var totalWeight = (
                from s in _installSteps
                select s.Weight
                ).Sum();

            var cumWeight = 0;

            // install all steps
            foreach (var step in _installSteps)
            {
                _log.Info("Starting installation step: " + step.Title);

                this.installerBgWorker.ReportProgress((cumWeight * 100)/ totalWeight, step.Title + "...");

                // continue
                try
                {
                    // start installing
                    step.PerformInstall();

                    _log.Info("Successfully completed installation step: " + step.Title);

                    // report progress
                    cumWeight += step.Weight;
                }
                catch (Exception ex)
                {
                    _log.Error("Installation step failed: " + step.Title, ex);

                    throw;
                }
            }

            // done
            this.installerBgWorker.ReportProgress(100, Resources.txtInstallDone);
        }

        private void installerBgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.filledBar.Value1 = e.ProgressPercentage;
            this.statusLabel.Text = (string)e.UserState;
        }

        private void installerBgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // failed?
            if (e.Error != null)
            {
                _log.Error("Failed to extract file", e.Error);

                this.filledBar.Value1 = 0;
                this.statusLabel.Text = Resources.txtFailed;

                QMessageBox.Show(
                    e.Error.Message,
                    Resources.txtInstallFailedTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
            }

            // cancel?
            if ((e.Error != null) || e.Cancelled)
            {
                QMessageBox.Show(
                    Resources.txtInstallAbortedText,
                    Resources.txtInstallAbortedTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );

                this.ParentWizard2.Close();

                return;
            }

            // installation successful
            QMessageBox.Show(
                Resources.txtInstallCompleteText,
                Resources.txtInstallCompleteTitle,
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
                );

            this.ParentWizard2.Close();
        }

        private void Step40_Install_CancelButtonClick(object sender, EventArgs e)
        {
            if (QMessageBox.Show(
                Resources.txtCancelVerifyText,
                Resources.txtCancelVerifyTitle,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question
                ) != DialogResult.Yes)
            {
                return;
            }

            this.CancelButtonEnabled = false;

            this.installerBgWorker.CancelAsync();
        }
    }
}
